﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace Pg.BioMedics.SDR.Web.Controls
{
    /// <summary>
    /// ViewHost control supporting AJAX navigation with Navigator class
    /// </summary>
    [ToolboxData("<{0}:ViewHost runat=\"server\"></{0}:ViewHost>")]
    [ToolboxItem(true)]
    [PersistChildren(true)]
    public class ViewHost : WebControl, IViewNavigator
    {
        #region Fields

        private string activeViewName;

        private string actionToolbarID;
        private ActionToolbar actionToolbar;

        private ContentPlaceHolder placeHolder;
        private UserControl control;

        private object parameter;

        private List<View> views = new List<View>();

        private string updatePanelID = Guid.NewGuid().ToString();

        #endregion

        #region Properties

        /// <summary>
        /// Gets / sets selected view name
        /// </summary>
        public string ActiveViewName
        {
            get
            {
                return GetViewName(ViewLocation);
            }
        }

        /// <summary>
        /// Gets / sets action toolbar id
        /// </summary>
        public string ActionToolbarID
        {
            get
            {
                return this.actionToolbarID;
            }

            set
            {
                this.actionToolbarID = value;
            }
        }        

        /// <summary>
        /// Gets / sets view control location
        /// </summary>
        public string ViewLocation
        {
            get
            {
                return ViewState["ViewLocation"] as string;
            }

            private set
            {
                ViewState["ViewLocation"] = value;
            }
        }

        /// <summary>
        /// Gets / sets view parameter. View must implement IHostedView interface in order to 
        /// </summary>
        public object Parameter
        {
            get
            {
                return this.parameter;
            }

            set
            {
                this.parameter = value;
            }
        }

        /// <summary>
        /// Gets list of views registered in this host
        /// </summary>
        public List<View> Views
        {
            get
            {
                return this.views;
            }
        }

        /// <summary>
        /// Gets / sets update panel id
        /// </summary>
        public string UpdatePanelID
        {
            get
            {
                return this.updatePanelID;
            }

            set
            {
                if (!String.IsNullOrEmpty(value))
                    this.updatePanelID = value;
            }
        }

        #endregion

        #region Event handlers

        /// <summary>
        /// This event handler is called when corresponding ActionToolbar assigned
        /// to this ViewHost by its Id (ActionToolbarID) raises the ActionInvoked event.
        /// </summary>
        /// <param name="sender">ActionToolbar control</param>
        /// <param name="e">Action parameters</param>
        private void actionToolbar_ActionInvoked(object sender, ActionInvokedEventArgs e)
        {
            LoadView(e.ViewName, e.Parameter);
        }

        #endregion

        #region Overriden methods

        protected override void OnInit(EventArgs e)
        {
            if (Page != null)
            {
                FindActionToolbar();               
                this.actionToolbar.ActionInvoked += new ActionInvokedEventHandler(actionToolbar_ActionInvoked);
            }

            UpdatePanel updatePanel = new UpdatePanel();
            updatePanel.ID = this.updatePanelID;
            updatePanel.Triggers.Add(new AsyncPostBackTrigger() { ControlID = this.actionToolbarID });            
            Controls.Add(updatePanel);

            this.placeHolder = new ContentPlaceHolder();
            updatePanel.ContentTemplateContainer.Controls.Add(this.placeHolder);
        }

        protected override void OnLoad(EventArgs e)
        {
            LoadView();            
        }

        #endregion

        #region Methods

        /// <summary>
        /// Loads user controls as a view from the location defined by
        /// ViewLocation property content
        /// </summary>
        private void LoadView()
        {
            if (!string.IsNullOrEmpty(ViewLocation))
            {
                this.placeHolder.Controls.Clear();
                this.control = (UserControl)Page.LoadControl(ViewLocation);

                if (this.control is IHostedView)
                {
                    IHostedView hostedView = this.control as IHostedView;
                    hostedView.Parameter = this.parameter;
                    hostedView.ViewNavigator = this;
                }

                this.placeHolder.Controls.Add(this.control);                
            }            
        }

        /// <summary>
        /// Loads given view defined by its user friendly name
        /// </summary>
        /// <param name="viewName">View name</param>
        public void LoadView(string viewName)
        {
            ViewLocation = GetViewLocation(viewName);
            LoadView();

            if (this.actionToolbar != null)
                this.actionToolbar.ActiveViewName = viewName;
        }

        /// <summary>
        /// Loads given view with given parameter
        /// </summary>
        /// <param name="viewName">View name</param>
        /// <param name="parameter">View parameter</param>
        public void LoadView(string viewName, object parameter)
        {
            Parameter = parameter;
            LoadView(viewName);            
        }

        #endregion

        #region Support methods

        private void FindActionToolbar()
        {
            // check in control model
            this.actionToolbar = Parent.FindControl(this.actionToolbarID) as ActionToolbar;
            if (this.actionToolbar == null)
                this.actionToolbar = Page.FindControl(this.actionToolbarID) as ActionToolbar;

            if (this.actionToolbar == null)
                throw new HttpException(String.Format("Action toolbar {0} does not exist on the page", this.actionToolbarID));
        }

        /// <summary>
        /// Gets location of user control (view) basing on it's name
        /// </summary>
        /// <param name="viewName">Unique view name</param>
        /// <returns>View location</returns>
        private string GetViewLocation(string viewName)
        {
            return (from view in this.views
                    where view.Name == viewName
                    select view.Src).FirstOrDefault();
        }

        /// <summary>
        /// Gets view name
        /// </summary>
        /// <param name="viewLocation"></param>
        /// <returns></returns>
        private string GetViewName(string viewLocation)
        {
            return (from view in this.views
                    where view.Src == viewLocation
                    select view.Name).FirstOrDefault();
        }

        #endregion
    }
}
